<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Cluster</title>
    <link rel="stylesheet" href="https://js.arcgis.com/3.14/dijit/themes/tundra/tundra.css">
    <link rel="stylesheet" href="https://js.arcgis.com/3.14/esri/css/esri.css">
    <style>
      html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
      #map{ margin: 0; padding: 0; }

      /* center the image in the popup */
      .esriViewPopup .gallery { margin: 0 auto !important; }
    </style>
    <script src="extras/cluster-module.js"></script>
    <script>
      let path = location.pathname.replace(/\/[^/]+$/, '') + 'extras/';
      if (typeof clusterUrl == 'undefined') {
          window.clusterUrl = location.origin + path;
      }
      // helpful for understanding dojoConfig.packages vs. dojoConfig.paths:
      // http://www.sitepen.com/blog/2013/06/20/dojo-faq-what-is-the-difference-packages-vs-paths-vs-aliases/
      var dojoConfig = { 
        paths: {
          extras: path
        }
      };
    </script>
    <script src="https://js.arcgis.com/3.14/"></script>
    <script>
      var map;
      require([
        "dojo/parser", 
        "dojo/ready",
        "dojo/_base/array",
        "esri/Color",
        "dojo/dom-style",
        "dojo/query",

        "esri/map", 
        "esri/request",
        "esri/graphic",
        "esri/geometry/Extent",

        'esri/layers/ArcGISTiledMapServiceLayer',
        "esri/symbols/SimpleMarkerSymbol",
        "esri/symbols/SimpleFillSymbol",
        "esri/symbols/PictureMarkerSymbol",
        "esri/renderers/ClassBreaksRenderer",

        "esri/layers/GraphicsLayer",
        "esri/SpatialReference",
        "esri/dijit/PopupTemplate",
        "esri/geometry/Point",
        "esri/geometry/webMercatorUtils",

        "extras/ClusterLayer",

        "dijit/layout/BorderContainer", 
        "dijit/layout/ContentPane", 
        "dojo/domReady!"
      ], function(
        parser, ready, arrayUtils, Color, domStyle, query,
        Map, esriRequest, Graphic, Extent,ArcGISTiledMapServiceLayer,
        SimpleMarkerSymbol, SimpleFillSymbol, PictureMarkerSymbol, ClassBreaksRenderer,
        GraphicsLayer, SpatialReference, PopupTemplate, Point, webMercatorUtils,
        ClusterLayer
      ) {
        ready(function() {
          parser.parse();

          var clusterLayer;
          var popupOptions = {
            "markerSymbol": new SimpleMarkerSymbol("circle", 20, null, new Color([0, 0, 0, 0.25])),
            "marginLeft": "20",
            "marginTop": "20"
          };
          map = new Map("map", {
            // basemap: "oceans",
            center: [-117.789, 33.543],
            zoom: 13
          });
          var basemap = new ArcGISTiledMapServiceLayer(
            //'http://services.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer'
            'https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer'
            //'https://sampleserver6.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer'
          );
          map.addLayer(basemap);
          map.on("load", function() {
            // hide the popup's ZoomTo link as it doesn't make sense for cluster features
            domStyle.set(query("a.action.zoomTo")[0], "display", "none");

            // get the latest 1000 photos from instagram/laguna beach
            var photos = esriRequest({
              url: "data/1000-photos.json",
              handleAs: "json"
            });
            photos.then(addClusters, error);
          });

          function addClusters(resp) {
            var photoInfo = {};
            var wgs = new SpatialReference({
              "wkid": 4326
            });
            photoInfo.data = arrayUtils.map(resp, function(p) {
              var latlng = new  Point(parseFloat(p.lng), parseFloat(p.lat), wgs);
              var webMercator = webMercatorUtils.geographicToWebMercator(latlng);
              var attributes = {
                "Caption": p.caption,
                "Name": p.full_name,
                "Image": p.image,
                "Link": p.link
              };
              return {
                "x": webMercator.x,
                "y": webMercator.y,
                "attributes": attributes
              };
            });

            // popupTemplate to work with attributes specific to this dataset
            var popupTemplate = new PopupTemplate({
              "title": "",
              "fieldInfos": [{
                "fieldName": "Caption",
                visible: true
              }, {
                "fieldName": "Name",
                "label": "By",
                visible: true
              }, {
                "fieldName": "Link",
                "label": "On Instagram",
                visible: true
              }],
              "mediaInfos": [{
                "title": "",
                "caption": "",
                "type": "image",
                "value": {
                  "sourceURL": "{Image}",
                  "linkURL": "{Link}"
                }
              }]
            });

            // cluster layer that uses OpenLayers style clustering
            clusterLayer = new ClusterLayer({
              "data": photoInfo.data,
              "distance": 100,
              "id": "clusters",
              "labelColor": "#fff",
              "labelOffset": 10,
              "resolution": map.extent.getWidth() / map.width,
              "singleColor": "#888",
              "singleTemplate": popupTemplate
            });
            var defaultSym = new SimpleMarkerSymbol().setSize(4);
            var renderer = new ClassBreaksRenderer(defaultSym, "clusterCount");

            var picBaseUrl = "img/";
            var blue = new PictureMarkerSymbol(picBaseUrl + "BluePin1LargeB.png", 32, 32).setOffset(0, 15);
            var green = new PictureMarkerSymbol(picBaseUrl + "GreenPin1LargeB.png", 64, 64).setOffset(0, 15);
            var red = new PictureMarkerSymbol(picBaseUrl + "RedPin1LargeB.png", 72, 72).setOffset(0, 15);
            renderer.addBreak(0, 2, blue);
            renderer.addBreak(2, 200, green);
            renderer.addBreak(200, 1001, red);

            clusterLayer.setRenderer(renderer);
            map.addLayer(clusterLayer);

            // close the info window when the map is clicked
            map.on("click", cleanUp);
            // close the info window when esc is pressed
            map.on("key-down", function(e) {
              if (e.keyCode === 27) {
                cleanUp();
              }
            });
          }

          function cleanUp() {
            map.infoWindow.hide();
            clusterLayer.clearSingles();
          }

          function error(err) {
            console.log("something failed: ", err);
          }

          // show cluster extents...
          // never called directly but useful from the console 
          window.showExtents = function() {
            var extents = map.getLayer("clusterExtents");
            if ( extents ) {
              map.removeLayer(extents);
            }
            extents = new GraphicsLayer({ id: "clusterExtents" });
            var sym = new SimpleFillSymbol().setColor(new Color([205, 193, 197, 0.5]));

            arrayUtils.forEach(clusterLayer._clusters, function(c, idx) {
              var e = c.attributes.extent;
              extents.add(new Graphic(new Extent(e[0], e[1], e[2], e[3], map.spatialReference), sym));
            }, this);
            map.addLayer(extents, 0);
          };
        });
      });
    </script>
  </head>
  
  <body>
    <div data-dojo-type="dijit/layout/BorderContainer" 
         data-dojo-props="design:'headline',gutters:false" 
         style="width: 100%; height: 100%; margin: 0;">
      <div id="map" 
           data-dojo-type="dijit/layout/ContentPane" 
           data-dojo-props="region:'center'"> 
      </div>
    </div>
  </body>
</html>

